package cn.iocoder.yudao.module.digital.service.cardchannel.impl.bh.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.system.OperatingSystemUtil;
import cn.iocoder.yudao.module.digital.framework.cardkey.config.CardKeyConfig;
import cn.iocoder.yudao.module.digital.service.cardchannel.constant.CardKeyThirdPartyApiConstant;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.EGiftHttpResponse;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.EGiftErrorResponse;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.ThirdPartyApiRequestTypeEnum;
import cn.iocoder.yudao.module.infra.constants.InfraHeaderConstants;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class CardKeyThirdPartyApiHttpUtil {
    private static final int SOCKET_TIMEOUT = 1000 * 60;
    private static final int CONNECT_TIMEOUT = 1000 * 30;
    private static SSLSocketFactory sslSocketFactory;
    private static CardKeyConfig cardKeyConfig;

    public static void initHttpClient(CardKeyConfig cardKeyConfig) throws Exception {
        CardKeyThirdPartyApiHttpUtil.cardKeyConfig = cardKeyConfig;
        String certPath = cardKeyConfig.getCertPath();
        final String macCertPath = cardKeyConfig.getMacCertPath();
        if (StrUtil.isNotEmpty(macCertPath) && OperatingSystemUtil.isMac()){
            certPath = macCertPath;
        }
        CardKeyThirdPartyApiHttpUtil.sslSocketFactory = getSSLSocketFactory(certPath, cardKeyConfig.getCertPassword());
    }

    private static SSLSocketFactory getSSLSocketFactory(String p12Path, String password) throws Exception {
        // 加载客户端证书
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new FileInputStream(new File(p12Path)), password.toCharArray());

        // 创建 SSL 上下文，加载客户端证书
        SSLContext sslContext = SSLContext.getInstance("TLS");
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password.toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), null, null);

        // Get SSLSocketFactory from the SSLContext
        return sslContext.getSocketFactory();
    }

    public static Map<String, String> createHeaders(String requestId, String mid, String tenantId, String orderNo) {
        return createHeaders(requestId, mid, tenantId, 0, orderNo);
    }

    public static Map<String, String> createHeaders(String requestId, String mid, String tenantId, Integer index, String orderNo) {
        final Map<String, String> headers = new HashMap<>();
        headers.put("requestId", requestId);
        headers.put("contractId", mid);
        if (StrUtil.isNotEmpty(tenantId)) {
            headers.put("TenantId", tenantId);
        }
        if (index != null) {
            // The number of times this same request has been attempted unsuccessfully before.
            // A value that is greater than zero will cause the service to view this request as a retry attempt and it will be treated idempotently.
            headers.put("previousAttempts", String.valueOf(index));
        }
        headers.put(InfraHeaderConstants.HEADER_BUSINESS_ID, orderNo);
        return headers;
    }

    public static EGiftHttpResponse sendRequest(int index, ThirdPartyApiRequestTypeEnum requestType, String url,
                                                Object requestParams, Map<String, String> headers) {
        final String requestBody = requestParams instanceof String ? (String) requestParams : JsonUtils.toJsonString(requestParams);
        log.info("调用黑鹰API-开始, index = {}, requestType = {}, url = {}, headers = {}, requestBody = {}",
                index, requestType, url, headers, requestBody);
        try {

            final HttpRequest request;
            if (requestType == ThirdPartyApiRequestTypeEnum.POST) {
                // 创建 POST 请求
                request = HttpRequest.post(url);
                request.body(requestBody);
            } else {
                request = HttpRequest.get(url);
                request.form((Map<String, Object>) requestParams);
            }

            request.setConnectionTimeout(CONNECT_TIMEOUT)
                    .setReadTimeout(SOCKET_TIMEOUT)
                    .setSSLSocketFactory(sslSocketFactory);

            final String proxyHost = cardKeyConfig.getProxyHost();
            final Integer proxyPort = cardKeyConfig.getProxyPort();
            if (StringUtil.isNotEmpty(proxyHost)) {
                request.setHttpProxy(proxyHost, proxyPort);
            }

            // header
            addHeader(headers, request);

            // 执行请求
            final HttpResponse response = request.execute();

            // 处理响应
            final int statusCode = response.getStatus();
            final String responseContent = response.body();
            if (statusCode == CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS) {
                log.info("调用黑鹰API-成功, index = {}, url = {}, statusCode = {}, responseContent = {}, headers = {}, requestBody = {}",
                        index, url, statusCode, responseContent, headers, requestBody);
                return new EGiftHttpResponse(statusCode, responseContent, null);
            } else {
                log.warn("调用黑鹰API-失败, index = {}, url = {}, statusCode = {}, responseContent = {}, headers = {}, requestBody = {}",
                        index, url, statusCode, responseContent, headers, requestBody);
                final EGiftErrorResponse errorResponse = parseEGiftErrorResponse(responseContent);
                return new EGiftHttpResponse(statusCode, responseContent, errorResponse);
            }
        } catch (Exception e) {
            log.warn(String.format("调用黑鹰API-异常, index = %s, url = %s, headers = %s, requestBody = %s",
                    index, url, headers, requestBody), e);
            return new EGiftHttpResponse(CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_EXCEPTION, null, null);
        }
    }

    private static EGiftErrorResponse parseEGiftErrorResponse(String responseContent) {
        try {
            final EGiftErrorResponse errorResponse = StrUtil.isNotEmpty(responseContent) ? JsonUtils.parseObject(responseContent, EGiftErrorResponse.class) : null;
            return errorResponse;
        } catch (Exception e) {
            return null;
        }
    }

    private static void addHeader(Map<String, String> headers, HttpRequest request) {
        request.header("Content-Type", "application/json");
        if (CollUtil.isNotEmpty(headers)) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                final String key = entry.getKey();
                final String value = entry.getValue();
                request.header(key, value);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        String url = "https://api.certification.blackhawknetwork.com/productCatalogManagement/v1/productCatalogs";
        String p12Path = "E:/cardkey/Byte-Topup-OneTreeHill-AU-API-CertificationService-GW.p12";
        String certPassword = "G1NKJT89YYMGNBT71VYPY3RTB4";
        SSLSocketFactory sslSocketFactory = getSSLSocketFactory(p12Path, certPassword);
        String result = HttpRequest.get(url)
                .timeout(20000)
                .setSSLSocketFactory(sslSocketFactory)
                .setHttpProxy("127.0.0.1", 7078)
                .execute().body();
        System.out.println(result);
    }

    private static void testGenCard() throws Exception {
        String url = "https://api.certification.blackhawknetwork.com/eGiftProcessing/v1/generateEGift";

        String requestBody = "{\"giftAmount\": \"5\", \"purchaserInfo\": {\"state\": \"UT\", \"countryCode\": \"USA\"}, \"productConfigurationId\": \"X50Y9TDPM6QQKYLHLX8NDD6Q14\", \"retrievalReferenceNumber\": \"000000000002\"}";

        String p12Path = "E:/cardkey/Byte-Topup-OneTreeHill-AU-API-CertificationService-GW.p12";
        String certPassword = "G1NKJT89YYMGNBT71VYPY3RTB4";

        Map<String, String> headers = createHeaders("b9c66c9d2f13480ebd4d8ba9748eb06e", "60300032972", "HQYYNV7FMNMDS7R24X6L05TWAC", "abc");

//        CloseableHttpClient httpClient = createHttpClient(p12Path, certPassword, null, null);
        EGiftHttpResponse response = sendRequest(0, ThirdPartyApiRequestTypeEnum.POST, url, requestBody, headers);
        System.out.println(response);

        FileUtil.writeBytes(response.getResponseContent().getBytes("utf-8"), "E:/cardkey/response.json");
    }

    private static void testQueryProduct() throws Exception {
        String url = "https://api.certification.blackhawknetwork.com/productCatalogManagement/v1/productCatalogs";
//        String url = "https://api.certification.blackhawknetwork.com/productCatalogManagement/v1/productCatalog/0C90WZA2N5LST9BSQBJ4TK5D6R";

        String requestBody = null;
//        String p12Path = "E:/cardkey/TEMP-BHNSandbox-DDP-US-API-CertificationService-GW.p12";
//        String certPassword = "MR70HKAMZFWX9H48985T8K841M";

        String p12Path = "E:/cardkey/Byte-Topup-OneTreeHill-AU-API-CertificationService-GW.p12";
        String certPassword = "G1NKJT89YYMGNBT71VYPY3RTB4";

        final Map<String, String> headers = new HashMap<>();
        headers.put("TenantId", "HQYYNV7FMNMDS7R24X6L05TWAC");

        EGiftHttpResponse response = sendRequest(0, ThirdPartyApiRequestTypeEnum.GET, url, requestBody, headers);
        System.out.println(response);

        FileUtil.writeBytes(response.getResponseContent().getBytes("utf-8"), "E:/cardkey/response.json");
    }

}
